package com.amt.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;


/**
 * @Title: WJWHttpUtil.java 
 * @Package com.amt.util 
 * @Description: TODO(省卫健委http工具类) 
 * @author 江伟  
 * @date 2021年01月3日 上午10:55:21
 * Copyright (c) ©1994-2021 Scjydz.com All Rights Reserved.
 */
@Slf4j
public class WJWHttpUtil {
    private static final String HTTP_PREFIX = "http://";
    private static final String HTTPS_PREFIX = "https://";
    /**
     * 请求超时时间
     */
    public static final int CONNECTION_TIMEOUT_DEFAULT = 30000;

    /**
     * 响应超时时间
     */
    public static final int SOCKET_TIMEOUT_DEFAULT = 50000;

    /**
     * 无限超时时间
     */
    public static final int INFINITE_TIMEOUT = 0;

    /**
     * 接收/传输数据时使用的默认socket缓冲字节大小
     */
    public static final int SOCKET_BUFFER_SIZE_DEFAULT = 81920;

    /**
     * 请求失败后重新尝试的次数
     */
    public static final int RETRY_COUNT_DEFAULT = 2;

    /**
     * 默认字符集
     */
    public static final String DEFAULT_CHARSET = "UTF-8";

    public static final CloseableHttpClient httpClient = buildHttpClient(SOCKET_TIMEOUT_DEFAULT);

    public static final CloseableHttpClient httpClientNoTimeout = buildHttpClient(INFINITE_TIMEOUT);
    private static CloseableHttpClient buildHttpClient(int socketTimeout) {
        // 设置最大连接数和每个host的最大连接数
        HttpClientBuilder httpClientBuilder = HttpClients.custom().setMaxConnTotal(2000).setMaxConnPerRoute(2000);
        // 内部默认使用 PoolingHttpClientConnectionManager 作为其连接管理器, 再次设置会覆盖下面其它参数的设置
        // httpClientBuilder.setConnectionManager(new PoolingHttpClientConnectionManager());
        // 设置服务器连接超时时间 及 服务器响应超时时间
        httpClientBuilder.setDefaultRequestConfig(RequestConfig.custom().setConnectionRequestTimeout(CONNECTION_TIMEOUT_DEFAULT).setSocketTimeout(socketTimeout).build());
        // 设置在关闭TCP连接时最大停留时间,是否禁用优化算法延迟发送数据 及 在非阻塞I/O情况下的服务器响应时间
        httpClientBuilder.setDefaultSocketConfig(SocketConfig.custom().setSoLinger(1500).setTcpNoDelay(true).setSoTimeout(socketTimeout).build());
        // 设置接收/传输数据时的buffer大小,及默认字符集
        httpClientBuilder.setDefaultConnectionConfig(ConnectionConfig.custom().setBufferSize(SOCKET_BUFFER_SIZE_DEFAULT).setCharset(Charset.forName(DEFAULT_CHARSET)).build());
        // 设置失败后重新尝试访问的处理器,不使用已经请求的连接
        httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(RETRY_COUNT_DEFAULT, false));
        return httpClientBuilder.build();
    }

    private static TrustManager myX509TrustManager = new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] arg0, String arg1)
                throws java.security.cert.CertificateException {
            // TODO Auto-generated method stub

        }
        @Override
        public void checkServerTrusted(X509Certificate[] arg0, String arg1)
                throws java.security.cert.CertificateException {
            // TODO Auto-generated method stub

        }
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }
    };

    public static byte[] readInputStream(InputStream inStream) throws Exception {
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = inStream.read(buffer)) != -1) {
            outStream.write(buffer, 0, len);
        }
        byte[] data = outStream.toByteArray();// 网页的二进制数据
        outStream.close();
        inStream.close();
        return data;
    }

    public static String getPostParam(Map<String, Object> params) throws Exception {
        StringBuffer buffer = new StringBuffer();
        for (String key : params.keySet()) {
            String urlKey = URLEncoder.encode(key, "UTF-8");
            String urlValue = URLEncoder.encode(String.valueOf(params.get(key)), "UTF-8");
            buffer.append(urlKey).append("=").append(urlValue).append("&");
        }
        String paramStr = buffer.toString();
        if (paramStr.endsWith("&") && paramStr.length() > 0) {
            paramStr = paramStr.substring(0, paramStr.length() - 1);
        }
        return paramStr;
    }

    public static String postForm(String url, Map<String, Object> params) throws Exception {
        log.info("请求的url {},输入参数{}", url, params);
        OutputStream out = null;
        if (!url.startsWith(HTTP_PREFIX) && !url.startsWith(HTTPS_PREFIX)) {
            url = HTTP_PREFIX + url;
        }
        URL localURL = new URL(url);
        URLConnection connection =null;
        if(url.toLowerCase().startsWith(HTTPS_PREFIX)){
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
            URL requestUrl = new URL(url);
            HttpsURLConnection httpsConn = (HttpsURLConnection)requestUrl.openConnection();
            httpsConn.setSSLSocketFactory(sslcontext.getSocketFactory());
            connection=httpsConn;
        }else{
            connection = (HttpURLConnection) localURL.openConnection();
        }
        connection.setRequestProperty("accept", "*/*");
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        connection.setDoOutput(true);
        connection.setDoInput(true);
        out = connection.getOutputStream();
        out.write(getPostParam(params).getBytes());
        out.flush();
        InputStream inStream = connection.getInputStream();
        String str = new String(readInputStream(inStream), "UTF-8");
        return str;
    }


    public static String postHttps(String url, String params) throws Exception {
        log.info("请求的url {},输入参数{}", url, params);
        OutputStream out = null;
        if (!url.startsWith(HTTP_PREFIX) && !url.startsWith(HTTPS_PREFIX)) {
            url = HTTP_PREFIX + url;
        }
        URL localURL = new URL(url);
        URLConnection connection =null;
        if(url.toLowerCase().startsWith(HTTPS_PREFIX)){
            SSLContext sslcontext = SSLContext.getInstance("TLSv1.1");
            sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
            URL requestUrl = new URL(url);
            HttpsURLConnection httpsConn = (HttpsURLConnection)requestUrl.openConnection();
            httpsConn.setSSLSocketFactory(sslcontext.getSocketFactory());
            connection=httpsConn;
        }else{
            connection = (HttpURLConnection) localURL.openConnection();
        }

        connection.setRequestProperty("Accept", "*/*");
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("user-agent", "Mozilla/6.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        connection.setDoOutput(true);
        connection.setDoInput(true);
        out = connection.getOutputStream();
        out.write(params.getBytes());
        out.flush();
        InputStream inStream = connection.getInputStream();
        String str = new String(readInputStream(inStream), "UTF-8");
        return str;
    }

    public static String postForm(String url, String params) throws Exception {
        log.info("请求的url {},输入参数{}", url, params);
        OutputStream out = null;
        if (!url.startsWith(HTTP_PREFIX) && !url.startsWith(HTTPS_PREFIX)) {
            url = HTTP_PREFIX + url;
        }
        URL localURL = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) localURL.openConnection();
        connection.setRequestProperty("accept", "*/*");
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        connection.setDoOutput(true);
        connection.setDoInput(true);
        out = connection.getOutputStream();
        out.write(params.getBytes());
        out.flush();
        InputStream inStream = connection.getInputStream();
        String str = new String(readInputStream(inStream), "UTF-8");
//		String str = "";
        return str;
    }




    public static String getForm(String url, String params) throws Exception {
        url = url + "?" + params;
        URL localURL = new URL(url);
        HttpURLConnection connection = null;
        if(url.startsWith(HTTPS_PREFIX)){
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
            URL requestUrl = new URL(url);
            HttpsURLConnection httpsConn = (HttpsURLConnection)requestUrl.openConnection();
            httpsConn.setSSLSocketFactory(sslcontext.getSocketFactory());
            connection=httpsConn;
        }else{
            connection = (HttpURLConnection) localURL.openConnection();
        }
        connection.setRequestProperty("accept", "*/*");
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        InputStream inStream = connection.getInputStream();
        String str = new String(readInputStream(inStream), "UTF-8");
        return str;
    }

    public static String getForm(String url, Map<String, Object> params) throws Exception {
        url = url + "?" + getPostParam(params);
        URL localURL = new URL(url);
        HttpURLConnection connection = null;
        if(url.startsWith(HTTPS_PREFIX)){
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(null, new TrustManager[]{myX509TrustManager}, null);
            URL requestUrl = new URL(url);
            HttpsURLConnection httpsConn = (HttpsURLConnection)requestUrl.openConnection();
            httpsConn.setSSLSocketFactory(sslcontext.getSocketFactory());
            connection=httpsConn;
        }else{
            connection = (HttpURLConnection) localURL.openConnection();
        }
        connection.setRequestProperty("accept", "*/*");
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        connection.setUseCaches(false);
        InputStream inStream = connection.getInputStream();
        String str = new String(readInputStream(inStream), "UTF-8");
        return str;
    }

    public static Map<String, Object> getMap(String key, Object value) {
        Map<String, Object> result = new HashMap<String, Object>();
        result.put(key, value);
        return result;
    }



}

